package com.nado.extensions.data;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.nado.extensions.reload.Reloadable;

@SuppressWarnings("unchecked")
public class DataHandlerProxy extends AbstractDataHandler {

	private ConcurrentHashMap<String, String> cachedValueMap = new ConcurrentHashMap<String, String>();
	private ConcurrentHashMap<String, List<String>> cachedValueListMap = new ConcurrentHashMap<String, List<String>>();

	private DataHandler dataHandler;

	public DataHandlerProxy(DataHandler dataHandler) {
		this.dataHandler = dataHandler;
	}

	protected void initialize() {
		if (dataHandler instanceof Reloadable) {
			((Reloadable) dataHandler).load();
		}
	}

	public void destroy() {
		dataHandler.destroy();
	}

	public boolean containsKey(String key) {
		return dataHandler.containsKey(key);
	}

	public String get(String key) throws DataHandlerException {
		if (key == null) {
			throw new IllegalArgumentException("key is null");
		}
		String value = cachedValueMap.get(key);
		if (value == null) {
			if (log.isDebugEnabled()) {
				log.debug("-- caching : key(" + key + "), value(" + value + ")");
			}
			value = dataHandler.get(key);
			cachedValueMap.put(key, value);
		}
		return value;
	}

	public String getRootName() {
		return dataHandler.getRootName();
	}

	public List<String> getValues(String key) {
		if (key == null) {
			throw new IllegalArgumentException("key is null");
		}

		List values = cachedValueListMap.get(key);
		if (values == null) {
			if (log.isDebugEnabled()) {
				log.debug("-- caching : key(" + key + "), value(" + values + ")");
			}
			values = dataHandler.getValues(key);
			cachedValueListMap.put(key, values);
		}
		return values;
	}

	public List<DataHandler> selectAll(String key) throws DataHandlerException {
		return wrap(dataHandler.selectAll(key));
	}

	public DataHandler peek(String key) {
		DataHandler subDataHander = dataHandler.peek(key);
		return subDataHander != null ? wrap(subDataHander) : null;
	}

	public DataHandler select(String key) throws DataHandlerException {
		return wrap(dataHandler.select(key));
	}

	public List<DataHandler> peekAll(String path) {
		return wrap(dataHandler.peekAll(path));
	}

	public List<DataHandler> peekChildren() {
		return wrap(dataHandler.peekChildren());
	}

	protected DataHandler wrap(DataHandler handler) {
		return new DataHandlerProxy(handler);
	}

	protected List<DataHandler> wrap(List<DataHandler> handlers) {
		List<DataHandler> wrapper = new ArrayList<DataHandler>(handlers.size());
		for (DataHandler handler : handlers) {
			wrapper.add(new DataHandlerProxy(handler));
		}
		return wrapper;
	}
}